#include"stdafx.h"
#include"FaceDetective.h"
#include<iostream>
#include<string.h>

using namespace std;

FaceDetective::FaceDetective()
{
}

FaceDetective::~FaceDetective()
{
}

int FaceDetective::report(void){
	cout<<"roger that."<<endl;
	return 0;
} 

int FaceDetective::detect(std::string source){

	static CvMemStorage* storage = 0;
	static CvHaarClassifierCascade* cascade = 0;
	const char* cascade_name = "C:/OpenCV2.1/data/haarcascades/haarcascade_frontalface_alt.xml";

	// Structure for getting video from camera or avi
	CvCapture* capture = 0;

	// Images to capture the frame from video or camera or from file
	IplImage *frame, *frame_copy = 0;

	// Used for calculations
	int optlen = strlen("--cascade=");

	// Input file name for avi or image file.
	const char* input_name;

//	input_name = argc > 1 ? argv[1] : 0;
	input_name = 0;

	// Load the HaarClassifierCascade
	cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
    
	// Check whether the cascade has loaded successfully. Else report and error and quit
	if( !cascade )
	{
		fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
		return -1;
	}
    
	// Allocate the memory storage
	storage = cvCreateMemStorage(0);
    
/*	// Find whether to detect the object from file or from camera.
	if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
		capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
	else
		capture = cvCaptureFromAVI( input_name ); 
*/

	// Check input type:
	// no input - from cam,  
	// input as folder - from images, 
	// input as .avi - from video
	if("NULL" == source)
	{
		capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
	}
	else
	{
		int ext_start = source.find_last_of(".");
		int ext_end = source.length();
		if("avi" == source.substr(ext_start + 1,ext_end))
//		if("avi" == source.substr(source.find_last_of("avi"),source.length()))
		{
			input_name = source.c_str();
			capture = cvCaptureFromAVI( input_name ); 
		}
		else
		{
			// single picture
			input_name = source.c_str();
			IplImage* img = cvLoadImage(input_name,1);
			detect_and_draw( img, storage, cascade);

		}
	}


	// Create a new named window with title: result
	cvNamedWindow( "result", 1 );

	// Find if the capture is loaded successfully or not.

	// If loaded succesfully, then:
	if( capture )
	{
		// Capture from the camera.
		for(;;)
		{
			// Capture the frame and load it in IplImage
			if( !cvGrabFrame( capture ))
				break;
			frame = cvRetrieveFrame( capture );

			// If the frame does not exist, quit the loop
			if( !frame )
				break;
            
			// Allocate framecopy as the same size of the frame
			if( !frame_copy )
				frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
											IPL_DEPTH_8U, frame->nChannels );

			// Check the origin of image. If top left, copy the image frame to frame_copy. 
			if( frame->origin == IPL_ORIGIN_TL )
				cvCopy( frame, frame_copy, 0 );
			// Else flip and copy the image
			else
				cvFlip( frame, frame_copy, 0 );
            
			// Call the function to detect and draw the face
			detect_and_draw( frame_copy, storage, cascade);

			// Wait for a while before proceeding to the next frame
			if( cvWaitKey( 10 ) >= 0 )
				break;
		}

		// Release the images, and capture memory
		cvReleaseImage( &frame_copy );
		cvReleaseCapture( &capture );
	}

	// If the capture is not loaded succesfully, then:
	else
	{
		// Assume the image to be lena.jpg, or the input_name specified
		const char* filename = input_name ? input_name : (char*)"lena.jpg";

		// Load the image from that filename
		IplImage* image = cvLoadImage( filename, 1 );

		// If Image is loaded succesfully, then:
		if( image )
		{
			// Detect and draw the face
			detect_and_draw( image, storage, cascade );

			// Wait for user input
			cvWaitKey(0);

			// Release the image memory
			cvReleaseImage( &image );
		}
		else
		{
			/* assume it is a text file containing the
			   list of the image filenames to be processed - one per line */
			FILE* f = fopen( filename, "rt" );
			if( f )
			{
				char buf[1000+1];

				// Get the line from the file
				while( fgets( buf, 1000, f ) )
				{

					// Remove the spaces if any, and clean up the name
					int len = (int)strlen(buf);
					while( len > 0 && isspace(buf[len-1]) )
						len--;
					buf[len] = '\0';

					// Load the image from the filename present in the buffer
					image = cvLoadImage( buf, 1 );

					// If the image was loaded succesfully, then:
					if( image )
					{
						// Detect and draw the face from the image
						detect_and_draw( image, storage, cascade );
                        
						// Wait for the user input, and release the memory
						cvWaitKey(0);
						cvReleaseImage( &image );
					}
				}
				// Close the file
				fclose(f);
			}
		}

	}
    
	// Destroy the window previously created with filename: "result"
	cvDestroyWindow("result");

	// return 0 to indicate successfull execution of the program
	return 0;

}

// Function to detect and draw any faces that is present in an image
void FaceDetective::detect_and_draw( IplImage* img, static CvMemStorage* storage, static CvHaarClassifierCascade* cascade)
{
	int scale = 1;

	// Create a new image based on the input image
	IplImage* temp = cvCreateImage( cvSize(img->width/scale,img->height/scale), 8, 3 );

	// Create two points to represent the face locations
	CvPoint pt1, pt2;
	int i;

	// Clear the memory storage which was used before
	cvClearMemStorage( storage );

	// Find whether the cascade is loaded, to find the faces. If yes, then:
	if( cascade )
	{

		// There can be more than one face in an image. So create a growable sequence of faces.
		// Detect the objects and store them in the sequence
		CvSeq* faces = cvHaarDetectObjects( img, cascade, storage,
											1.1, 2, CV_HAAR_DO_CANNY_PRUNING,
											cvSize(40, 40) );

		// Loop the number of faces found.
		for( i = 0; i < (faces ? faces->total : 0); i++ )
		{
		   // Create a new rectangle for drawing the face
			CvRect* r = (CvRect*)cvGetSeqElem( faces, i );

			// Find the dimensions of the face,and scale it if necessary
			pt1.x = r->x*scale;
			pt2.x = (r->x+r->width)*scale;
			pt1.y = r->y*scale;
			pt2.y = (r->y+r->height)*scale;

			// Draw the rectangle in the input image
			cvRectangle( img, pt1, pt2, CV_RGB(255,0,0), 3, 8, 0 );
		}
	}

	// Show the image in the window named "result"
	cvShowImage( "result", img );

	// Release the temp image created.
	cvReleaseImage( &temp );
}



int FaceDetective::SetSource(int src){
	if (src >= 0 && src <= 3){
		source = src;
		return 0;
	}
	else
	{
		return -1;
	}
}